#include <bits/stdc++.h>

#define in read()
#define pb push_back

using namespace std;

using ll = long long;
using vec = vector<int>;

int read() {
	int x = 0; bool f = 0; char ch = getchar();
	while(!isdigit(ch)) f |= ch == '-',ch = getchar();
	while(isdigit(ch)) x = (x << 1) + (x << 3) + (ch ^ 48),ch = getchar();
	return f ? -x : x;
}

const int N = 5e5 + 10;
const int mod = 998244353;

int rt[N],n,m,mxd;
int dfn[N],R[N],tim,fa[N],dep[N];
vec G[N],req[N];

int upd(int x) {return x + (x >> 31 & mod);}

namespace st {
	const int L = 2e7;
	int val[L],mut[L],ndn,ch[L][2];
	vec trash;
	int newwd() { int x; if(trash.size()) return x = trash.back(),trash.pop_back(),x; return ++ndn;}
	int newd() { int x = newwd(); val[x] = 0; mut[x] = 1; ch[x][0] = ch[x][1] = 0; return x;}
	
	void mul(int o,int v) { if(!o) return; val[o] = (ll) val[o] * v % mod; mut[o] = (ll) mut[o] * v % mod;}
	
	void pushdn(int o) { if(mut[o] != 1) mul(ch[o][0],mut[o]) , mul(ch[o][1],mut[o]) , mut[o] = 1;}
	
	void upd(int &o,int pos,int l = 0,int r = mxd) {
		o = newd(); val[o] = 1; if(l == r) return; int mid = l + r >> 1; pushdn(o);// no need to pushdn .
		if(pos <= mid) upd(ch[o][0],pos,l,mid); else upd(ch[o][1],pos,mid + 1,r);
	}
	
	void merge(int &x,int y,int &mu1,int &mu2,int l = 0,int r = mxd) {
		if(!x && !y) return; if(!x) return mu1 = :: upd(mu1 + val[y] - mod), mul(y,mu2), x = y , void();
		if(!y) return mu2 = :: upd(mu2 + val[x] - mod) , mul(x,mu1) , void();
		if(l == r) {
			int vx = val[x],vy = val[y]; mu1 = :: upd(mu1 + vy - mod); val[x] = :: upd((ll) val[x] * mu1 % mod + (ll) val[y] * mu2 % mod - mod);
			mu2 = :: upd(mu2 + vx - mod); trash.pb(y);
			return;
		}
		pushdn(x); pushdn(y);  int mid = l + r >> 1;
		merge(ch[x][0],ch[y][0],mu1,mu2,l,mid); merge(ch[x][1],ch[y][1],mu1,mu2,mid + 1,r);
		val[x] = :: upd(val[ch[x][0]] + val[ch[x][1]] - mod); trash.pb(y);
	}
	
	int query(int x,int xl,int xr,int l = 0,int r = mxd) {
		if(!x) return 0; if(xl == l && xr == r) return val[x]; int mid = l + r >> 1; pushdn(x);
		if(xr <= mid) return query(ch[x][0],xl,xr,l,mid); else if(xl > mid) return query(ch[x][1],xl,xr,mid + 1,r);
		else return :: upd(query(ch[x][0],xl,mid,l,mid) + query(ch[x][1],mid + 1,xr,mid + 1,r) - mod);
	}
}

void dfs(int x,int p) { dep[x] = dep[p] + 1; fa[x] = p; mxd = max(mxd,dep[x]); for(auto y : G[x]) if(y ^ p) dfs(y,x);}

void dfs(int x) {
	int mx = 0; for(auto y : req[x]) mx = max(mx,dep[y]); st :: upd(rt[x],mx);
	for(auto y : G[x]) {
		if(y == fa[x]) continue; dfs(y); int mu1 = st :: query(rt[y],0,dep[x]),mu2 = 0; st :: merge(rt[x],rt[y],mu1,mu2);
	}
}

int main() {
	n = in; for(int i = 1,u,v;i < n;i++) u = in,v = in,G[u].pb(v),G[v].pb(u);
	m = in; for(int i = 1,u,v;i <= m;i++) u = in,v = in,req[v].pb(u);
	dfs(1,0); dfs(1); printf("%d\n",st :: query(rt[1],0,0));
	return 0;
}
